package sf.database.template.enjoy.ext;

import com.jfinal.template.Directive;
import com.jfinal.template.Env;
import com.jfinal.template.TemplateException;
import com.jfinal.template.expr.ast.Expr;
import com.jfinal.template.io.Writer;
import com.jfinal.template.stat.Scope;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class InDirective extends Directive {
    @Override
    public void exec(Env env, Scope scope, Writer writer) {
        SqlPara sqlPara = (SqlPara) scope.get(SqlKit.SQL_PARA_KEY);
        if (sqlPara == null) {
            throw new TemplateException("#para directive invoked by getSqlPara(...) method only", location);
        }
        if (exprList.length() == 1) {
            Expr expr = exprList.getExpr(0);
            Object o = expr.eval(scope);
            if (o != null) {
                List<Object> paraValues = new ArrayList<>();
                String str = in(o, paraValues);
                write(writer, str);
                for (Object v : paraValues) {
                    sqlPara.addPara(v);
                }
            }
        }
    }

    public static String in(Object o, List<Object> paraValues) {
        String ret = "";
        if (o == null) {
            return ret;
        }
        StringBuilder sb = new StringBuilder();
        if (o instanceof Collection) {
            Collection<Object> values = (Collection<Object>) o;
            if (values.isEmpty()) {
                return ret;
            }
            sb.append("in(");
            boolean f = false;
            for (Object val : values) {
                sb.append(f ? "," : "").append("?");
                paraValues.add(val);
                f = true;
            }
            sb.append(")");
        } else if (o.getClass().isArray()) {
            int length = Array.getLength(o);
            if (length == 0) {
                return ret;
            }
            sb.append("in(");
            for (int i = 0; i < length; i++) {
                Object val = Array.get(o, i);
                sb.append(i > 0 ? "," : "").append("?");
                paraValues.add(val);
            }
            sb.append(")");
        } else {
            sb.append("in(?)");
            paraValues.add(o);
        }
        ret = sb.toString();
        return ret;
    }
}
